package com.heima.search.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.json.JsonData;
import com.heima.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.search.vos.SearchArticleVo;
import com.heima.search.service.ArticleSearchService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

/**
 * 类的模板注释
 *
 * @author Mr.杨
 * @week 星期五
 * @date 2024-08-30    17:19:18
 */
@Service
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Resource
    private ElasticsearchClient elasticsearchClient;
    private static final String INDEX_NAME = "app_info_article";

    /**
     * es文章分页检索
     */
    @Override
    public ResponseResult<List<SearchArticleVo>> search(UserSearchDto dto) throws IOException {
        //1.构建query对象
        Query query = this.buildBasicQuery(dto);
        //分页参数
        int size = dto.getPageSize();
        int from = dto.getFromIndex();
        //2.搜索数据
        SearchResponse<SearchArticleVo> searchResponse = this.elasticsearchClient.search(builder -> builder
                        .index(INDEX_NAME)
                        .query(query) //设置查询条件
                        .size(size) //分页参数
                        .from(from) //分页参数
                        .sort(s -> s.field(f -> f.field("publishTime").order(SortOrder.Desc))) //按照发布时间倒序查询
                        .highlight(h -> h.fields("title", f -> f
                                .requireFieldMatch(false)
                                .preTags("<font style='color: red; font-size: inherit;'>")
                                .postTags("</font>"))) //设置标题高亮
                , SearchArticleVo.class);
        //3.结果封装返回
        List<SearchArticleVo> searchArticleVos = CollStreamUtil.toList(searchResponse.hits().hits(), hit -> {
            SearchArticleVo searchArticleVo = hit.source();
            //处理高亮
            assert searchArticleVo != null;
            if (CollUtil.isNotEmpty(hit.highlight())) {
                String hTitle = StrUtil.join("", hit.highlight().get("title"));
                searchArticleVo.setH_title(hTitle);
            } else {
                searchArticleVo.setH_title(searchArticleVo.getTitle());
            }
            return searchArticleVo;
        });

        return ResponseResult.okResult(searchArticleVos);
    }

    private Query buildBasicQuery(UserSearchDto dto) {
        //构造布尔查询
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();

        if (StrUtil.isEmpty(dto.getSearchWords())) {
            //搜索全部
            boolQueryBuilder.must(m -> m.matchAll(ma -> ma));
        } else {
            boolQueryBuilder.must(m -> m.match(mm -> mm.field("all").query(dto.getSearchWords())));
        }

        //添加时间过滤条件
        if (ObjectUtil.isNotEmpty(dto.getMinBehotTime())) {
            boolQueryBuilder.filter(f -> f.range(r -> r.field("publishTime").lt(JsonData.of(dto.getMinBehotTime().getTime()))));
        }

        return new Query.Builder()
                .bool(boolQueryBuilder.build())
                .build();
    }
}
